package xyz.thoughtset.viewer.modules.step.executor;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import xyz.thoughtset.viewer.common.exc.entity.ExcInfo;
import xyz.thoughtset.viewer.common.exc.exceptions.ExecException;
import xyz.thoughtset.viewer.modules.ds.core.factory.ExecutorManager;
import xyz.thoughtset.viewer.modules.step.entity.BlockParam;
import xyz.thoughtset.viewer.modules.step.entity.QueryBlock;
import xyz.thoughtset.viewer.modules.step.service.QueryBlockService;

import java.util.*;

@Component
public class SimpleBlockExecutor {
    private final ExpressionParser parser = new SpelExpressionParser();

    @Autowired
    private QueryBlockService queryBlockService;
    @Autowired
    private ExecutorManager executorManager;




    public Map executeQuery(String apiId,Map params){
        Map contentMap = new HashMap(params);
        List<QueryBlock> blocks = queryBlockService.listByPId(apiId);
        for (QueryBlock block : blocks) {
            Object queryResult;
            try{
                queryResult = blockQuery(block,contentMap);
            }catch (ExecException e){
                throw e.addApiId(apiId);
            }catch (Exception e){
                ExecException exc = ExcInfo.buildAndThrowExc(e,params);
                exc.addBlockId(block.getId());
                exc.addApiId(apiId);
                throw exc;
            }
            String key = block.getTitle();
            Object val = queryResult;
            if (block.resultWasSingle() && !ObjectUtils.isEmpty(queryResult)){
                if (val instanceof List){
                    val = ((List)queryResult).get(0);
                }
            }else{
                if (!(val instanceof Collection)){
                    val = new ArrayList<>();
                    ((ArrayList) val).add(queryResult);
                }
            }
            contentMap.put(key,val);
        }

        return contentMap;
    }

//    private List blockQuery(QueryBlock block,Map contentMap){
//        QueryBody queryBody = queryBodyService.getById(block.getBodyId());
//        Map tmpParamsMap = new HashMap();
//        List<BlockParam> blockParams = queryBlockService.blockParams(block.getId());
//        if (Objects.nonNull(blockParams)){
//            StandardEvaluationContext context = new StandardEvaluationContext();
//            context.setVariable("p", contentMap);
//            Map<String,QueryParam> queryMap = queryBody.getParams()
//                    .stream()
//                    .collect(Collectors.toMap(QueryParam::getId, Function.identity(), (existing, replacement) -> existing));
//            for (BlockParam blockParam : blockParams){
//                if(!StringUtils.hasText(blockParam.getDataExp())){
//                    continue;
//                }
//                String exp =blockParam.getDataExp();
//                exp = blockParam.getDataExp().startsWith("['")?exp:"['"+exp;
//                exp = blockParam.getDataExp().endsWith("']")?exp:exp+"']";
//                Object value = parser.parseExpression("#p"+exp).getValue(context);
//                QueryParam queryParam = queryMap.get(blockParam.getQpId());
//                tmpParamsMap.put(queryParam.getTitle(),
//                        Convert.convert(TypeConstants.TYPE_MAP.get(queryParam.getDataType()),value));
//            }
//        }
//        return simpleQueryExecutor.doQuery(queryBody.getQuery(),tmpParamsMap,queryBody.getDsId());
//    }

    private Object blockQuery(QueryBlock block,Map contentMap){
        Map tmpParamsMap = new HashMap();
        List<BlockParam> blockParams = queryBlockService.blockParams(block.getId());
        if (Objects.nonNull(blockParams)){
            StandardEvaluationContext context = new StandardEvaluationContext();
            context.setVariable("p", contentMap);
            for (BlockParam blockParam : blockParams){
                if(!StringUtils.hasText(blockParam.getDataExp())){
                    continue;
                }
                String exp =blockParam.getDataExp();
                exp = blockParam.getDataExp().startsWith("['")?exp:"['"+exp;
                exp = blockParam.getDataExp().endsWith("']")?exp:exp+"']";
                Object value = parser.parseExpression("#p"+exp).getValue(context);
                tmpParamsMap.put(blockParam.getQpId(),value);
            }
        }
        //todo: cache执行
        //划分if loop mcp fun
        return executorManager.execute(block.getBodyId(),tmpParamsMap);
    }


}
